package co.edu.usbcali.unidades.presentation.backingBeans;

import co.edu.usbcali.unidades.exceptions.*;
import co.edu.usbcali.unidades.modelo.*;
import co.edu.usbcali.unidades.modelo.dto.ReservaDTO;
import co.edu.usbcali.unidades.presentation.businessDelegate.BusinessDelegatorView;
import co.edu.usbcali.unidades.utilities.*;

import com.icesoft.faces.async.render.RenderManager;
import com.icesoft.faces.async.render.Renderable;
import com.icesoft.faces.component.ext.HtmlCommandButton;
import com.icesoft.faces.component.ext.HtmlInputText;
import com.icesoft.faces.component.ext.HtmlSelectOneMenu;
import com.icesoft.faces.component.selectinputdate.SelectInputDate;
import com.icesoft.faces.context.DisposableBean;
import com.icesoft.faces.webapp.xmlhttp.FatalRenderingException;
import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
import com.icesoft.faces.webapp.xmlhttp.RenderingException;
import com.icesoft.faces.webapp.xmlhttp.TransientRenderingException;

import java.math.BigDecimal;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.Vector;

import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.DataModel;
import javax.faces.model.SelectItem;

public class ReservaView extends DataSource implements Renderable,
		DisposableBean {
	private HtmlInputText txtEstCodigo_Estado;
	private HtmlInputText txtPriCodigo_PropietarioInmueble;
	private HtmlInputText txtZocCodigo_ZonaComun;
	private HtmlInputText txtResCodigo;
	private SelectInputDate txtResFecha;
	private SelectInputDate txtResHoraFin;
	private SelectInputDate txtResHoraInicio;
	private HtmlCommandButton btnSave;
	private HtmlCommandButton btnModify;
	private HtmlCommandButton btnDelete;
	private HtmlCommandButton btnClear;
	private boolean renderDataTable;
	private boolean flag = true;
	private RenderManager renderManager;
	private PersistentFacesState state = PersistentFacesState.getInstance();
	private List<Reserva> reserva;
	private List<ReservaDTO> reservaDTO;

	// Variables para el comboZonas comunes....
	private HtmlSelectOneMenu cmbTipoZonasComunes;
	private List<ZonaComun> listaZonas;
	private List<SelectItem> tipos;

	public ReservaView() {
		super("");
	}

	public String action_volver() {
		action_clear();
		return "volver";
	}

	public String action_clear() {
		txtEstCodigo_Estado.setValue(null);
		txtEstCodigo_Estado.setDisabled(true);

		txtPriCodigo_PropietarioInmueble.setValue(null);
		txtPriCodigo_PropietarioInmueble.setDisabled(true);

		cmbTipoZonasComunes.setValue("-1");
		cmbTipoZonasComunes.setDisabled(false);

		txtResFecha.setValue(null);
		txtResFecha.setDisabled(false);

		txtResHoraFin.setValue(null);
		txtResHoraFin.setDisabled(true);

		txtResHoraInicio.setValue(null);
		txtResHoraInicio.setDisabled(true);

		txtResCodigo.setValue(null);
		txtResCodigo.setDisabled(true);

		btnSave.setDisabled(true);
		btnDelete.setDisabled(true);
		btnModify.setDisabled(true);
		btnClear.setDisabled(false);

		return "";
	}

	public void listener_txtId(ActionEvent e) {
		try {
			String codigoPro= FacesUtils.getSession().getAttribute("codPro").toString();
			Reserva entity = BusinessDelegatorView.buscarReserva(
					cmbTipoZonasComunes.getValue().toString(),FacesUtils.checkDate(txtResFecha), codigoPro);
			//la reserva no existe...
			if (entity == null) {
				txtEstCodigo_Estado.setValue("Activa");
				txtEstCodigo_Estado.setDisabled(true);				
				txtPriCodigo_PropietarioInmueble.setValue(FacesUtils.getSession().getAttribute("codPro").toString());
				txtPriCodigo_PropietarioInmueble.setDisabled(true);				
				cmbTipoZonasComunes.setDisabled(false);				
				txtResFecha.setDisabled(false);				
				txtResHoraFin.setDisabled(false);				
				txtResHoraInicio.setDisabled(false);
				txtResCodigo.setValue(BusinessDelegatorView.darNumberReserva());
				txtResCodigo.setDisabled(true);				
				btnSave.setDisabled(false);
				btnDelete.setDisabled(true);
				btnModify.setDisabled(true);
				btnClear.setDisabled(false);
				
			//la reserva existe
			} else {
				//la reserva esta inactiva...
				if(entity.getEstado().getEstCodigo().equals("2")){
					
				//la reserva esta activa...
				}else{
					
				}
				
				txtResFecha.setDisabled(false);
				txtResHoraFin.setValue(entity.getResHoraFin());
				txtResHoraFin.setDisabled(false);
				txtResHoraInicio.setValue(entity.getResHoraInicio());
				txtResHoraInicio.setDisabled(false);
				txtEstCodigo_Estado.setValue(entity.getEstado().getEstCodigo());
				txtEstCodigo_Estado.setDisabled(false);
				txtPriCodigo_PropietarioInmueble.setValue(entity
						.getPropietarioInmueble().getPriCodigo());
				txtPriCodigo_PropietarioInmueble.setDisabled(false);
				cmbTipoZonasComunes.setValue(entity.getZonaComun()
						.getZocCodigo());
				cmbTipoZonasComunes.setDisabled(false);
				txtResCodigo.setValue(entity.getResCodigo());
				txtResCodigo.setDisabled(true);
				btnSave.setDisabled(true);
				btnDelete.setDisabled(false);
				btnModify.setDisabled(false);
				btnClear.setDisabled(false);
			}
		} catch (Exception e1) {
			FacesUtils.addErrorMessage(e1.getMessage());
		}

	}

	public String action_save() {
		try {
			BusinessDelegatorView.saveReserva(FacesUtils
					.checkString(txtResCodigo), FacesUtils
					.checkDate(txtResFecha), FacesUtils
					.checkDate(txtResHoraFin), FacesUtils
					.checkDate(txtResHoraInicio), FacesUtils
					.checkString(txtEstCodigo_Estado), FacesUtils
					.checkString(txtPriCodigo_PropietarioInmueble), FacesUtils
					.checkString(cmbTipoZonasComunes));
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYSAVED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		return "";
	}

	public String action_delete() {
		try {
			BusinessDelegatorView.deleteReserva(FacesUtils
					.checkString(txtResCodigo));
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYDELETED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		return "";
	}

	public String action_modify() {
		try {
			BusinessDelegatorView.updateReserva(FacesUtils
					.checkString(txtResCodigo), FacesUtils
					.checkDate(txtResFecha), FacesUtils
					.checkDate(txtResHoraFin), FacesUtils
					.checkDate(txtResHoraInicio), FacesUtils
					.checkString(txtEstCodigo_Estado), FacesUtils
					.checkString(txtPriCodigo_PropietarioInmueble), FacesUtils
					.checkString(txtZocCodigo_ZonaComun));
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYMODIFIED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		return "";
	}

	public String action_modifyWitDTO(String resCodigo, Date resFecha,
			Date resHoraFin, Date resHoraInicio, String estCodigo_Estado,
			String priCodigo_PropietarioInmueble, String zocCodigo_ZonaComun)
			throws Exception {
		try {
			BusinessDelegatorView.updateReserva(resCodigo, resFecha,
					resHoraFin, resHoraInicio, estCodigo_Estado,
					priCodigo_PropietarioInmueble, zocCodigo_ZonaComun);
			renderManager.getOnDemandRenderer("ReservaView").requestRender();
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYMODIFIED);
		} catch (Exception e) {
			// renderManager.getOnDemandRenderer("ReservaView").requestRender();
			FacesUtils.addErrorMessage(e.getMessage());
			throw e;
		}

		return "";
	}

	public List<Reserva> getReserva() {
		if (flag) {
			try {
				reserva = BusinessDelegatorView.getReserva();
				flag = false;
			} catch (Exception e) {
				flag = true;
				FacesUtils.addErrorMessage(e.getMessage());
			}
		}

		return reserva;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setReserva(List<Reserva> reserva) {
		this.reserva = reserva;
	}

	public boolean isRenderDataTable() {
		try {
			if (flag) {
				if (BusinessDelegatorView.findTotalNumberReserva() > 0) {
					renderDataTable = true;
				} else {
					renderDataTable = false;
				}
			}

			flag = false;
		} catch (Exception e) {
			renderDataTable = false;
			e.printStackTrace();
		}

		return renderDataTable;
	}

	public DataModel getData() {
		state = PersistentFacesState.getInstance();

		if (onePageDataModel == null) {
			onePageDataModel = new LocalDataModel(pageSize);
		}

		return onePageDataModel;
	}

	/**
	 * This is where the Object data is retrieved from the database and returned
	 * as a list of objects for display in the UI.
	 */
	private DataPage<Reserva> getDataPage(int startRow, int pageSize) {
		// Retrieve the total number of objects from the database. This
		// number is required by the DataPage object so the paginator will know
		// the relative location of the page data.
		int totalNumberReserva = 0;

		try {
			totalNumberReserva = BusinessDelegatorView.findTotalNumberReserva()
					.intValue();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Calculate indices to be displayed in the ui.
		int endIndex = startRow + pageSize;

		if (endIndex > totalNumberReserva) {
			endIndex = totalNumberReserva;
		}

		try {
			reserva = BusinessDelegatorView.findPageReserva(sortColumnName,
					sortAscending, startRow, endIndex - startRow);

			// Remove this Renderable from the existing render groups.
			// leaveRenderGroups();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Add this Renderable to the new render groups.
		// joinRenderGroups();
		// Reset the dirtyData flag.
		onePageDataModel.setDirtyData(false);
		// This is required when using Hibernate. If the SessionManager is not
		// cleared or closed objects are cached and stale objects will show up
		// in the table.
		// This way, the detached objects are reread from the database.
		// This call is not required with Hibernate, which uses a Query Hint
		// to clear the l2 cache in the DAO.
		flag = true;

		return new DataPage<Reserva>(totalNumberReserva, startRow, reserva);
	}

	public DataModel getDataDTO() {
		state = PersistentFacesState.getInstance();

		if (onePageDataModel == null) {
			onePageDataModel = new LocalDataModelDTO(pageSize);
		}

		return onePageDataModel;
	}

	/**
	 * This is where the Object data is retrieved from the database and returned
	 * as a list of objects for display in the UI.
	 */
	private DataPage<ReservaDTO> getDataPageDTO(int startRow, int pageSize) {
		// Retrieve the total number of objects from the database. This
		// number is required by the DataPage object so the paginator will know
		// the relative location of the page data.
		int totalNumberReserva = 0;

		try {
			totalNumberReserva = BusinessDelegatorView.findTotalNumberReserva()
					.intValue();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Calculate indices to be displayed in the ui.
		int endIndex = startRow + pageSize;

		if (endIndex > totalNumberReserva) {
			endIndex = totalNumberReserva;
		}

		try {
			reserva = BusinessDelegatorView.findPageReserva(sortColumnName,
					sortAscending, startRow, endIndex - startRow);

			if (Utilities.validationsList(reserva)) {
				reservaDTO = new ArrayList<ReservaDTO>();

				for (Reserva reservaTmp : reserva) {
					ReservaDTO reservaDTO2 = new ReservaDTO();
					reservaDTO2.setResCodigo(reservaTmp.getResCodigo()
							.toString());
					reservaDTO2.setResFecha(reservaTmp.getResFecha());
					reservaDTO2.setResHoraFin(reservaTmp.getResHoraFin());
					reservaDTO2.setResHoraInicio(reservaTmp.getResHoraInicio());
					reservaDTO2.setEstCodigo_Estado((reservaTmp.getEstado()
							.getEstCodigo() != null) ? reservaTmp.getEstado()
							.getEstCodigo().toString() : null);
					reservaDTO2
							.setPriCodigo_PropietarioInmueble((reservaTmp
									.getPropietarioInmueble().getPriCodigo() != null) ? reservaTmp
									.getPropietarioInmueble().getPriCodigo()
									.toString()
									: null);
					reservaDTO2
							.setZocCodigo_ZonaComun((reservaTmp.getZonaComun()
									.getZocCodigo() != null) ? reservaTmp
									.getZonaComun().getZocCodigo().toString()
									: null);
					reservaDTO2.setReserva(reservaTmp);
					reservaDTO2.setReservaView(this);
					reservaDTO.add(reservaDTO2);
				}
			}

			// Remove this Renderable from the existing render groups.
			leaveRenderGroups();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Add this Renderable to the new render groups.
		joinRenderGroups();
		// Reset the dirtyData flag.
		onePageDataModel.setDirtyData(false);
		// This is required when using Hibernate. If the SessionManager is not
		// cleared or closed objects are cached and stale objects will show up
		// in the table.
		// This way, the detached objects are reread from the database.
		// This call is not required with Hibernate, which uses a Query Hint
		// to clear the l2 cache in the DAO.
		flag = true;

		return new DataPage<ReservaDTO>(totalNumberReserva, startRow,
				reservaDTO);
	}

	protected boolean isDefaultAscending(String sortColumn) {
		return true;
	}

	/**
	 * This method is called when a render call is made from the server. Render
	 * calls are only made to views containing an updated record. The data is
	 * marked as dirty to trigger a fetch of the updated record from the
	 * database before rendering takes place.
	 */
	public PersistentFacesState getState() {
		onePageDataModel.setDirtyData();

		return state;
	}

	/**
	 * This method is called from faces-config.xml with each new session.
	 */
	public void setRenderManager(RenderManager renderManager) {
		this.renderManager = renderManager;
	}

	public void renderingException(RenderingException arg0) {
		if (arg0 instanceof TransientRenderingException) {
		} else if (arg0 instanceof FatalRenderingException) {
			// Remove from existing Customer render groups.
			leaveRenderGroups();
		}
	}

	/**
	 * Remove this Renderable from existing uiCustomerBeans render groups.
	 * OnDemandRenderers are named/created using the underlying Customer Number.
	 */
	private void leaveRenderGroups() {
		if (Utilities.validationsList(reservaDTO)) {
			for (ReservaDTO reservaTmp : reservaDTO) {
				renderManager.getOnDemandRenderer("ReservaView").remove(this);
			}
		}
	}

	/**
	 * Add this Renderable to the new uiCustomerBeans render groups.
	 * OnDemandRenderers are named/created using the underlying Customer Number.
	 */
	private void joinRenderGroups() {
		if (Utilities.validationsList(reservaDTO)) {
			for (ReservaDTO reservaTmp : reservaDTO) {
				renderManager.getOnDemandRenderer("ReservaView").add(this);
			}
		}
	}

	public void dispose() throws Exception {
	}

	public RenderManager getRenderManager() {
		return renderManager;
	}

	public void setState(PersistentFacesState state) {
		this.state = state;
	}

	public HtmlInputText getTxtEstCodigo_Estado() {
		return txtEstCodigo_Estado;
	}

	public void setTxtEstCodigo_Estado(HtmlInputText txtEstCodigo_Estado) {
		this.txtEstCodigo_Estado = txtEstCodigo_Estado;
	}

	public HtmlInputText getTxtPriCodigo_PropietarioInmueble() {
		return txtPriCodigo_PropietarioInmueble;
	}

	public void setTxtPriCodigo_PropietarioInmueble(
			HtmlInputText txtPriCodigo_PropietarioInmueble) {
		this.txtPriCodigo_PropietarioInmueble = txtPriCodigo_PropietarioInmueble;
	}

	public HtmlInputText getTxtZocCodigo_ZonaComun() {
		return txtZocCodigo_ZonaComun;
	}

	public void setTxtZocCodigo_ZonaComun(HtmlInputText txtZocCodigo_ZonaComun) {
		this.txtZocCodigo_ZonaComun = txtZocCodigo_ZonaComun;
	}

	public SelectInputDate getTxtResFecha() {
		return txtResFecha;
	}

	public void setTxtResFecha(SelectInputDate txtResFecha) {
		this.txtResFecha = txtResFecha;
	}

	public SelectInputDate getTxtResHoraFin() {
		return txtResHoraFin;
	}

	public void setTxtResHoraFin(SelectInputDate txtResHoraFin) {
		this.txtResHoraFin = txtResHoraFin;
	}

	public SelectInputDate getTxtResHoraInicio() {
		return txtResHoraInicio;
	}

	public void setTxtResHoraInicio(SelectInputDate txtResHoraInicio) {
		this.txtResHoraInicio = txtResHoraInicio;
	}

	public HtmlInputText getTxtResCodigo() {
		return txtResCodigo;
	}

	public void setTxtResCodigo(HtmlInputText txtResCodigo) {
		this.txtResCodigo = txtResCodigo;
	}

	public HtmlCommandButton getBtnSave() {
		return btnSave;
	}

	public void setBtnSave(HtmlCommandButton btnSave) {
		this.btnSave = btnSave;
	}

	public HtmlCommandButton getBtnModify() {
		return btnModify;
	}

	public void setBtnModify(HtmlCommandButton btnModify) {
		this.btnModify = btnModify;
	}

	public HtmlCommandButton getBtnDelete() {
		return btnDelete;
	}

	public void setBtnDelete(HtmlCommandButton btnDelete) {
		this.btnDelete = btnDelete;
	}

	public HtmlCommandButton getBtnClear() {
		return btnClear;
	}

	public void setBtnClear(HtmlCommandButton btnClear) {
		this.btnClear = btnClear;
	}

	public void setRenderDataTable(boolean renderDataTable) {
		this.renderDataTable = renderDataTable;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	public List<ReservaDTO> getReservaDTO() {
		return reservaDTO;
	}

	public void setReservaDTO(List<ReservaDTO> reservaDTO) {
		this.reservaDTO = reservaDTO;
	}

	public TimeZone getTimeZone() {
		return java.util.TimeZone.getDefault();
	}

	public HtmlSelectOneMenu getCmbTipoZonasComunes() {
		listaZonas = new ArrayList<ZonaComun>();
		tipos = new ArrayList<SelectItem>();
		try {

			listaZonas = BusinessDelegatorView.getZonaComun();
			SelectItem itm = new SelectItem("-1", "--Seleccione Uno--");
			tipos.add(itm);
			for (int i = 0; i < listaZonas.size(); i++) {
				SelectItem itm2 = new SelectItem(listaZonas.get(i)
						.getZocCodigo(), listaZonas.get(i).getZocNombre());
				tipos.add(itm2);
			}
		} catch (Exception e) {
			//
		}
		return cmbTipoZonasComunes;
	}

	public void setCmbTipoZonasComunes(HtmlSelectOneMenu cmbTipoZonasComunes) {
		this.cmbTipoZonasComunes = cmbTipoZonasComunes;
	}

	public List<ZonaComun> getListaZonas() {
		return listaZonas;
	}

	public void setListaZonas(List<ZonaComun> listaZonas) {
		this.listaZonas = listaZonas;
	}

	public List<SelectItem> getTipos() {
		return tipos;
	}

	public void setTipos(List<SelectItem> tipos) {
		this.tipos = tipos;
	}

	/**
	 * A special type of JSF DataModel to allow a datatable and datapaginator to
	 * page through a large set of data without having to hold the entire set of
	 * data in memory at once. Any time a managed bean wants to avoid holding an
	 * entire dataset, the managed bean declares this inner class which extends
	 * PagedListDataModel and implements the fetchData method. fetchData is
	 * called as needed when the table requires data that isn't available in the
	 * current data page held by this object. This requires the managed bean
	 * (and in general the business method that the managed bean uses) to
	 * provide the data wrapped in a DataPage object that provides info on the
	 * full size of the dataset.
	 */
	private class LocalDataModel extends PagedListDataModel {
		public LocalDataModel(int pageSize) {
			super(pageSize);
		}

		public DataPage<Reserva> fetchPage(int startRow, int pageSize) {
			// call enclosing managed bean method to fetch the data
			return getDataPage(startRow, pageSize);
		}
	}

	private class LocalDataModelDTO extends PagedListDataModel {
		public LocalDataModelDTO(int pageSize) {
			super(pageSize);
		}

		public DataPage<ReservaDTO> fetchPage(int startRow, int pageSize) {
			// call enclosing managed bean method to fetch the data
			return getDataPageDTO(startRow, pageSize);
		}
	}
}
